home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / Source ƒ.sea / Source ƒ / emacs source ƒ / MAIN.C < prev    next >
Encoding:
Text File  |  1992-06-28  |  33.2 KB  |  959 lines  |  [TEXT/MARC]

  1. /*
  2.  * This program is in public domain; written by Dave G. Conroy.
  3.  * This file contains the main driving routine, and some keyboard processing
  4.  * code, for the MicroEMACS screen editor.
  5.  *
  6.  * REVISION HISTORY:
  7.  *
  8.  * 1.0  Steve Wilhite, 30-Nov-85
  9.  *      - Removed the old LK201 and VT100 logic. Added code to support the
  10.  *        DEC Rainbow keyboard (which is a LK201 layout) using the the Level
  11.  *        1 Console In ROM INT. See "rainbow.h" for the function key defs
  12.  *      Steve Wilhite, 1-Dec-85
  13.  *      - massive cleanup on code in display.c and search.c
  14.  *
  15.  * 2.0  George Jones, 12-Dec-85
  16.  *      - Ported to Amiga.
  17.  *
  18.  * 3.0  Daniel Lawrence, 29-Dec-85
  19.  *      - rebound keys/added new fast buffered I/O for AMIGA
  20.  *    - added META- repeat commands
  21.  *    - added reposition default to center screen (yeah!)
  22.  *    - changed exit with modified buffers message
  23.  *    - made filesave tell us what it is doing
  24.  *    - changed search string entry to terminate with <ESC>
  25.  *      so we can use <NL> in search/replace strings
  26.  *    - updated version number in mode line to 3.0
  27.  *    12-Jan-86
  28.  *    - Added code to reconize the Search/replace functions
  29.  *    - Added code to perform search/replace & query functions
  30.  *    14-Jan-86
  31.  *    - moved search logic to separate function in search.c
  32.  *    - added replace and query replace functions
  33.  *    - separated out control key expansions to be used by others in search.c
  34.  *    15-Jan-86
  35.  *    - changed "visiting" to finding
  36.  *    - changed yes/no responces to not need return
  37.  *    - cleaned up various messages
  38.  *    16-jan-86
  39.  *    - fixed spurious spawn message in MSDOS
  40.  *    - added ^X-S synonime to save command
  41.  *    - moved escape to shell to ^X-C
  42.  *    21-jan-86
  43.  *    - added code to suspend shell under BSD
  44.  *    22-jan-86
  45.  *    - added function key support (SPEC) under MSDOS
  46.  *    - Abort now prints [Aborted] on message line
  47.  *    23-jan-86
  48.  *    - Added modes and commends to set/unset them
  49.  *    24-jan-86
  50.  *    - Added Goto Line command
  51.  *    - added Rename Buffer command
  52.  *    28-jan-86
  53.  *    - added goto beginning and end of paragraph commands (META-P/META-N)
  54.  *    - re-wrote kdelete to use realloc. gained MUCH speed here when
  55.  *      doing large wipes both on UNIX and MSDOS. Changed kill buffer
  56.  *      allocation block size from 256 bytes to 1 k
  57.  *    29-jan-86
  58.  *    - moved extern function declarations to efunc.h
  59.  *    - made name[] name binding table
  60.  *    30-jan-86
  61.  *    - fixed Previous/Next paragraph command not to wrap around EOF
  62.  *    - added Fill Paragraph command (META-Q)
  63.  *    4-feb-86
  64.  *    - added code to properly display long lines, scrolling them right
  65.  *      to left
  66.  *    5-feb-85
  67.  *    - rewrote code to right/left scroll...much better
  68.  *    - added shifted arror keys on IBMPC
  69.  *    6-feb-85
  70.  *    - add option to allow forword-word to jump to beginning of
  71.  *      next word instead of end of current one. This is different from
  72.  *      other emacs' but can be configured off in estruct.h
  73.  *    - added VIEW mode to allow a buffer to be read only
  74.  *       (-v switch on command line will activate this)
  75.  *    - changed quick exit to write out ALL changed buffers!!!
  76.  *      MAKE SURE YOU KNOW THIS WHEN META-Zing
  77.  *    10-feb-86
  78.  *    - added handling of lines longer than allowed on file read in
  79.  *      (they wrap on additional lines)
  80.  *    - made having space clear the message line and NOT insert itself
  81.  *      a configuration option in ed.h
  82.  *    11-feb-86
  83.  *    - added Describe-command and Help commands.
  84.  *    13-feb-86
  85.  *    - added View file command (^X ^V) and finished HELP command
  86.  *    14-feb-86
  87.  *    - added option to let main loop skip update if type ahead commands
  88.  *       are queued up
  89.  *    16-feb-86
  90.  *    - added Insert File command
  91.  *    17-feb-86
  92.  *    - added scroll next window up/down commands
  93.  *    18-feb-86
  94.  *    - added CMODE indentation
  95.  *    - re-arranged header files to standerdize extern and global
  96.  *      definitions
  97.  *    - changed version number to 3.2
  98.  *    - added numeric arguments to search, reverse search and
  99.  *      search and replace
  100.  *    24-feb-86
  101.  *    - added Bind To Key function (^C for now) to allow the user
  102.  *      to change his command keys
  103.  *    - added Unbind key function (M-^C for now)
  104.  *    - added execute named command to execute unbound commands (M-X)
  105.  *    - added describe bindings command (not bound)
  106.  *    - changed version number to 3.3
  107.  *    25-feb-86
  108.  *    - scrapped CERROR mode (too many compilers)
  109.  *    - added EXACT mode for case sensitive searchers
  110.  *    26-feb-86
  111.  *    - added command completion on execute named command and
  112.  *      all routined grabbing a command name
  113.  *    - adding execute-command-line command and its support functions
  114.  *      (in preporation for sourcing files)
  115.  *    - added Execute Buffer command
  116.  *    27-feb-86
  117.  *    - added execute(source) file command and added code to automatically
  118.  *      execute emacs.rc (or .emacsrc on UNIX) before initial read in
  119.  *    - changed version number to 3.4
  120.  *    4-mar-86
  121.  *    - changed word delete to be consistant with word move (it gets
  122.  *      rid of the inter word space now) This is configurable with the
  123.  *      NFWORD symbol in estruct.h
  124.  *    - added B_ACTIVE entry to the buffer table. Let emacs read multiple
  125.  *      file names from the command line and only read them in as needed
  126.  *    5-mar-85
  127.  *    - rewrote command line parser to get rid of my patchy code
  128.  *    - changed version number to 3.5
  129.  *    1-apr-86
  130.  *    - added support for Aztec C 3.20e under MSDOS
  131.  *    - fixed bug in mlwrite on ADM3's and thier ilk under V7
  132.  *    - added insertion of pounds in column one under CMODE
  133.  *    - changed version number to 3.6
  134.  *    3-apr-86
  135.  *    - added next-buffer command (^X-X)
  136.  *    5-apr-86
  137.  *    - added kill paragraph command (M-^W)
  138.  *    - changed fill-paragraph to leave 2 spaces after a period at the
  139.  *      end of a word.
  140.  *    - added OVERWRITE mode
  141.  *    7-apr-86
  142.  *    - fixed overwrite mode to handle tabs
  143.  *    8-apr-86
  144.  *    - added add/delete global mode (<ESC>M & <ESC> ^M) commands
  145.  *    9-apr-86
  146.  *    - added insert space command
  147.  *    - moved bindings around        ^C    insert space
  148.  *                    M-K    bind-to-key
  149.  *                    INSERT    insert space
  150.  *                    DELETE    forwdel
  151.  *    - added hunt forward and hunt reverse commands
  152.  *    10-apr-86
  153.  *    - fixed bug in DOBUF with non-terminated command string
  154.  *    15-apr-86
  155.  *    - fixed tab expansion bug in DISPLAY which hung the AMIGA
  156.  *      (send in by Dawn Banks)
  157.  *    - fixed curcol problen if forwline/backline during keyboard
  158.  *      macro execution (sent in by Ernst Christen)
  159.  *    - added AMIGA function/cursor key support
  160.  *    - fixed nonterminating <NL> replacement bug
  161.  *    - fixed word wrapping problems
  162.  *    16-apr-86
  163.  *    - updated documentation and froze development for 3.6 net release
  164.  *    23-apr-86    version 3.6a
  165.  *    - added forground and background colors. Setable with the
  166.  *      add mode commands for the moment
  167.  *    24-apr-86
  168.  *    - added command to pipe CLI output to a buffer
  169.  *    25-apr-86
  170.  *    - added Dana Hoggat's code to replace lattice's sick system()
  171.  *      function, now we no longer care what the switchar is.
  172.  *    - cleaned up the positioning on several of the spawing commands
  173.  *    26-apr-86
  174.  *    - added a output flush in vttidy(). Unix really appreciates this.
  175.  *    - added filter-buffer (^X#) command to send a buffer through
  176.  *      a dos filter
  177.  *    - made automatic CMODE on .c and .h file compilation dependant
  178.  *      in estruct.h
  179.  *    1-may-86
  180.  *    - optimized some code in update(). It certainly need a lot more.
  181.  *    - added AZTEC profiling capabilities. These are conditional on
  182.  *      the APROF symbol in estruct.h
  183.  *    2-may-86
  184.  *    - added (u)ndo command in query-replace. undoes last repalce.
  185.  *    6-may-86
  186.  *    - re-orginized and wrote the update() function in display.c
  187.  *      now my color hacks are in the right places and the code can be
  188.  *      understood.
  189.  *    [Released version 3.6f for BETA test sites]
  190.  *    8-may-86
  191.  *    - fixed bug in new display routine to wrap cursor on extended
  192.  *      lines at the right time
  193.  *    - modified the buffer-position command to give reasonable info
  194.  *    9-may-86
  195.  *    - improved the word wrap algorithm as not to discard non-space
  196.  *      delimiters. The backscan now looks for white space rather than
  197.  *      !inword().
  198.  *    [Released version 3.6g to Krannert]
  199.  *    10-may-86
  200.  *    - Added IBMPC.C an IBM-PC specific display driver. This makes paging
  201.  *      4-6 times faster. Also made some conditional changes to DISPLAY.C
  202.  *      to eliminate the pscreen[] if using the PC driver.
  203.  *    [changed version number to 3.6i]
  204.  *    12-may-86
  205.  *    - added delete-window (^X 0) command to dispose of a single window
  206.  *    - fixed problem with multiple prefixes from a command line which
  207.  *      was reported by John Gamble
  208.  *    14-may-86
  209.  *    - Added AZTEC support for the IBMPC display driver. Had to
  210.  *      readjust some includes and defines for this.
  211.  *    - fixed bug in delete-window.
  212.  *    - fixed some bizarre behavior with the cursor after coming back
  213.  *      from spawn calls.
  214.  *    [changed version number to 3.7 Freezing development for net release]
  215.  *    15-may-86
  216.  *    - (that didn't last long...) Added execute-macro-(1 thru 20) commands
  217.  *      to execute macro buffers (named "[Macro nn]")
  218.  *    - changed BFTEMP to BFINVS and cleaned up treatment of invisable
  219.  *      buffers.
  220.  *    16-may-86
  221.  *    - added store-macro (unbound) to store any executed command lines to
  222.  *      macro buffer.
  223.  *    - added clear-message-line (unbound) command to do just that
  224.  *    - added resize-window command to change a window's size to the
  225.  *      specified argument
  226.  *    - improved help's logic not to re-read the file if it was already
  227.  *      in a buffer
  228.  *    - added MAGIC mode to all structures and command tables, but the
  229.  *      regular expression code that John Gamble is writting is not ready.
  230.  *    18-may-86
  231.  *    - added interactive prompt requests in command line execution. IE
  232.  *      while executing a macro, a parameter starting with an at sign (@)
  233.  *      causes emacs to prompt with the rest of the parameter and return
  234.  *      the resulting input as the value of the parameter.
  235.  *    - added arguments to split-current-window to force the cursor into
  236.  *      the upper or lower window.
  237.  *    20-may-86
  238.  *    - added support for the Microsoft C compiler as per the changes
  239.  *      send in by Oliver Sharp
  240.  *    - made some upgrades and fixes for VMS sent in by Guy Streeter
  241.  *    21-may-86
  242.  *    - fixed an AZTEC bug in ttgetc by clearing the upper byte
  243.  *    - fixed buf in CMODE with #preprocesser input (bug fix submitted by
  244.  *      Willis of unknown path)
  245.  *    - added support of alternative startup file ( @<filename> ) in
  246.  *      the command line
  247.  *    - added ^Q quoting in interactive input (mlreplyt()).
  248.  *    - added re-binding of meta-prefix and ctlx-prefix
  249.  *    22-may-86
  250.  *    - reorginize getkey routines to make more sense and let prefix
  251.  *      binding work properly.
  252.  *    23-may-86
  253.  *    - checked new code on BSD4.2 made a few fixes
  254.  *    - added optional fence matching while in CMODE
  255.  *    - added goto and search command line arguments by Mike Spitzer
  256.  *    26-may-86
  257.  *    - added parameter fetching from buffers
  258.  *    27-may-86
  259.  *    - fixed some HP150 bugs......
  260.  *    31-may-86
  261.  *    - Added Wang PC keyboard support from modifications by
  262.  *      Sid Shapiro @ Wang Institute
  263.  *    - Fixed some reverse video bugs with code submitted by Peter Chubb
  264.  *    - Fixed bug in nextbuffer reported by Dave Forslund
  265.  *    - added system V support (USG) from Linwood Varney
  266.  *    2-jun-86
  267.  *    - changed defines to just define one unix define (for example,
  268.  *      just define BSD for Unix BSD 4.2)
  269.  *    - Added Incremental search functions written by D. R. Banks
  270.  *      in file ISEARCH.C
  271.  *    - added insert-string (unbound) command to help the macro
  272.  *      language out.
  273.  *    - added unmark-buffer (M-~) command to turn off the current buffers
  274.  *      change flag
  275.  *    - fixed nxtarg to truncate strings longer than asked for max length
  276.  *    4-jun-86
  277.  *    - added special characters in command line tokens. Tidle (~) is
  278.  *      the special leadin character for "nrtb".
  279.  *    - Fixed bad ifdef in aztec code so it could look at HOME dir
  280.  *      for startup, help, and emacs.rc files
  281.  *    6-jun-86
  282.  *    - make delete word commands clear the kill buffer if not after another
  283.  *      kill command
  284.  *    11-jun-86
  285.  *    - made ~@ in string arguments pass as char(192) to nxtarg() so one can
  286.  *      quote @ at the beginning of string arguments
  287.  *    - changed buffer size vars in listbuffers() to long (for big files)
  288.  *    - re-wrote buffer-position command to be much faster
  289.  *    12-jun-86
  290.  *    - added count-words (M-^C) command to count the words/chars and
  291.  *      lines in a region
  292.  *    - changed regions so they could be larger than 65535 (short ->
  293.  *      long in the REGION structure)
  294.  *    - changed ldelete() and all callers to use a long size. The kill
  295.  *      buffer will still have a problem >65535 that can not be solved
  296.  *      until I restructure it.
  297.  *    - grouped paragraph commands and word count together under symbol
  298.  *      WORDPRO to allow them to be conditionally made (or not)
  299.  *    13-jun-86
  300.  *    - re-wrote kill buffer routines again. Now they support an unlimited
  301.  *      size kill buffer, and are (in theory) faster.
  302.  *    - changed delete-next-word (M-D) to not eat the newline after a word,
  303.  *      instead it checks and eats a newline at the cursor.
  304.  *    17-jun-85
  305.  *    - added numeric argument to next/previous-window to access the nth
  306.  *      window from the top/bottom
  307.  *    - added support for the data General 10 MSDOS machine
  308.  *    - added save-window (unbound) and restore-window (unbound) commands
  309.  *      for the use of the menu script. Save-window remembers which window
  310.  *      is current, and restore-window returns the cursor to that window.
  311.  *    20-jun-86
  312.  *    - fixed a bug with the fence matching locking up near the beginning
  313.  *    of a buffer
  314.  *    - added argument to update to selectivaly force a complete update
  315.  *    - added update-screen (unbound) command so macros can force a
  316.  *      screen update
  317.  *    21-jun-86
  318.  *    - rearranged token() and nxtarg() calls so that command names and
  319.  *      repeat counts could also be prompted and fetched from buffers
  320.  *    - added write-message (unbound) command to write out a message
  321.  *      on the message line (for macros)
  322.  *    - changed ifdef's so that color modes are reconized as legal in
  323.  *      b/w version, and simply do nothing (allowing us to use the same
  324.  *      script files)
  325.  *    [Released version 3.7 on July 1 to the net and elswhere]
  326.  *    2-jul-86
  327.  *    - Changed search string terminator to always be the meta character
  328.  *      even if it is rebound.
  329.  *    3-jul-86
  330.  *    - removed extra calls to set color in startup code. This caused the
  331.  *      original current window always to be the global colors.
  332.  *    7-jul-86
  333.  *    - Fixed bugs in mlreplyt() so to work properly with all terminators
  334.  *      including control and spec characters
  335.  *    22-jul-86
  336.  *    - fixed replaces() so that it will return FALSE properly on the
  337.  *      input of the replacement string.
  338.  *    - added a definition for FAILED as a return type.....
  339.  *    - changed version number to 3.7b
  340.  *    23-jul-86
  341.  *    - fixed o -> 0 problem in termio.c
  342.  *    - made ^U universal-argument re-bindable
  343.  *    - wrote atoi() for systems (like aztec) where it acts screwy
  344.  *    - changed version number to 3.7c
  345.  *    25-jul-86
  346.  *    - make ^G abort-command rebindable
  347.  *    29-jul-86
  348.  *    - added HP110 Portable Computer support
  349.  *    - changed version number to 3.7d
  350.  *    30-jul-86
  351.  *    - Fixed a couple of errors in the new VMS code as pointer
  352.  *      out by Ken Shacklford
  353.  *    - split terminal open/close routines into screen and keyboard
  354.  *      open/close routines
  355.  *    - closed the keyboard during all disk I/O so that OS errors
  356.  *      can be respoded to correctly (especially on the HP150)
  357.  *    - changed version number to 3.7e
  358.  *    31-jul-86
  359.  *    - added label-function-key (unbound) command under symbol FLABEL
  360.  *      (primarily for the HP150)
  361.  *    4-aug-86
  362.  *    - added fixes for MicroSoft C as suggested by ihnp4!ihuxm!gmd1
  363.  *        <<remember to fix [list] deletion bug as reported
  364.  *          by craig@hp-pcd>>
  365.  *    8-aug-86
  366.  *    - fixed beginning misspelling error everywhere
  367.  *    - fixed some more MSC errors
  368.  *    - changed version number to 3.7g
  369.  *    20-aug-86
  370.  *    - fixed CMODE .h scanning bug
  371.  *    - changed version number to 3.7h
  372.  *    30-aug-86
  373.  *    - fixed killing renamed [list] buffer (it can't) as submited
  374.  *      by James Aldridge
  375.  *    - Added code to allow multiple lines to display during
  376.  *      vertical retrace
  377.  *    9-sep-86
  378.  *    - added M-A (apropos) command to list commands containing a substring.
  379.  *    - fixed an inefficiency in the display update code submited
  380.  *      by William W. Carlson (wwc@pur-ee)
  381.  *    10-sep-86
  382.  *    - added Dana Hoggatt's code for encryption and spliced it into the
  383.  *      proper commands. CRYPT mode now triggers encryption.
  384.  *    - added -k flag to allow encryption key (no spaces) in command line
  385.  *    14-sep-86
  386.  *    - added missing lastflag/thisflag processing to docmd()
  387.  */
  388.  
  389. #include        <stdio.h>
  390.  
  391. /* make global definitions not external */
  392. #define    maindef
  393.  
  394. #include        "estruct.h"    /* global structures and defines */
  395. #include    "efunc.h"    /* function declarations and name table    */
  396. #include    "edef.h"    /* global definitions */
  397. #include    "ebind.h"    /* default key bindings */
  398.  
  399. #if     VMS
  400. #include        <ssdef.h>
  401. #define GOOD    (SS$_NORMAL)
  402. #endif
  403.  
  404. #ifndef GOOD
  405. #define GOOD    0
  406. #endif
  407.  
  408. #if    APROF    /* Declarations needed for AZTEC C profiling */
  409. int _Corg();    /* first address of program */
  410. int _Cend();    /* last address of program */
  411.  
  412. short monbuf[NBUCK];    /* buffer for gather info */
  413. #endif
  414.  
  415. main(argc, argv)
  416. char    *argv[];
  417. {
  418.         register int    c;
  419.         register int    f;
  420.         register int    n;
  421.         register int    mflag;
  422.     register BUFFER *bp;
  423.     register int    ffile;        /* first file flag */
  424.     register int    carg;        /* current arg to scan */
  425.     register int    startf;        /* startup executed flag */
  426.     int basec;            /* c stripped of meta character */
  427.     int viewflag;            /* are we starting in view mode? */
  428.         int gotoflag;                   /* do we need to goto a line at start? */
  429.         int gline;                      /* if so, what line? */
  430.         int searchflag;                 /* Do we need to search at start? */
  431.         char bname[NBUFN];        /* buffer name of file to read */
  432. #if    CRYPT
  433.     int eflag;            /* encrypting on the way in? */
  434.     char ekey[NPAT];        /* startup encryption key */
  435. #endif
  436.  
  437. #if    APROF
  438.     /* if we are doing AZTEC C profiling, start it up */
  439.     /*_intr_sp(18);     set clock interupt for 60/second */
  440.     monitor(_Corg, _Cend, monbuf, NBUCK, 0);
  441. #endif
  442.  
  443.     /* initialize the editor and process the command line arguments */
  444.         strcpy(bname, "main");    /* default buffer name */
  445.         vtinit();        /* Displays.            */
  446.         edinit(bname);        /* Buffers, windows.    */
  447.     viewflag = FALSE;    /* view mode defaults off in command line */
  448.     gotoflag = FALSE;    /* set to off to begin with */
  449.     searchflag = FALSE;    /* set to off to begin with */
  450.     ffile = TRUE;        /* no file to edit yet */
  451.     startf = FALSE;        /* startup file not executed yet */
  452. #if    CRYPT
  453.     eflag = FALSE;        /* no encryption by default */
  454. #endif
  455. #if    COLOR
  456.     curwp->w_fcolor = gfcolor;        /* and set colors    */
  457.     curwp->w_bcolor = gbcolor;
  458. #endif
  459.     
  460.     /* scan through the command line and get the files to edit */
  461.     for (carg = 1; carg < argc; ++carg) {
  462.         /* if its a switch, process it */
  463.         if (argv[carg][0] == '-') {
  464.             switch (argv[carg][1]) {
  465.                 case 'v':    /* -v for View File */
  466.                 case 'V':
  467.                     viewflag = TRUE;
  468.                     break;
  469.                 case 'e':    /* -e for Edit file */
  470.                 case 'E':
  471.                     viewflag = FALSE;
  472.                     break;
  473.                 case 's':    /* -s for initial search string */
  474.                 case 'S':
  475.                     searchflag = TRUE;
  476.                     strcpy(pat,&argv[carg][2]);
  477.                     break;
  478.                 case 'g':    /* -g for initial goto */
  479.                 case 'G':    
  480.                     gotoflag = TRUE;
  481.                     gline = atoi(&argv[carg][2]);
  482.                     break;
  483. #if    CRYPT
  484.                 case 'k':    /* -k<key> for code key */
  485.                 case 'K':
  486.                     if (argv[carg][2] == 0)
  487.                         eflag = FALSE;
  488.                     else {
  489.                         eflag = TRUE;
  490.                         strcpy(ekey, &argv[carg][2]);
  491.                     }
  492.                     break;
  493. #endif
  494.                 default:    /* unknown switch */
  495.                     /* ignore this for now */
  496.                     break;
  497.             }
  498.         } else     /* check for a macro file */
  499.             if (argv[carg][0]== '@') {
  500.  
  501.             if (startup(&argv[carg][1]) == TRUE)
  502.                 startf = TRUE;    /* don't execute emacs.rc */
  503.  
  504.         } else {    /* process a file name */
  505.             /* if we haven't run emacs.rc, do it now */
  506.             if (startf == FALSE) {
  507.                 startup("");
  508.                 startf = TRUE;
  509. #if    COLOR
  510.                 curwp->w_fcolor = gfcolor;
  511.                 curwp->w_bcolor = gbcolor;
  512. #endif
  513.             }
  514.  
  515.             /* set up a buffer for this file */
  516.                     makename(bname, argv[carg]);
  517.  
  518. #if    CRYPT
  519.             /* set up for de-cryption if needed */
  520.             if (eflag) {
  521.                 curbp->b_mode |= MDCRYPT;
  522.                 strcpy(curbp->b_key, ekey);
  523.                 crypt((char *)NULL, 0);
  524.                 crypt(curbp->b_key, strlen(curbp->b_key));
  525.             }
  526. #endif
  527.  
  528.             /* if this is the first file, read it in */
  529.             if (ffile) {
  530.                 bp = curbp;
  531.                 makename(bname, argv[carg]);
  532.                 strcpy(bp->b_bname, bname);
  533.                 strcpy(bp->b_fname, argv[carg]);
  534.                 if (readin(argv[carg], (viewflag==FALSE))
  535.                                 == ABORT) {
  536.                     strcpy(bp->b_bname, "main");
  537.                     strcpy(bp->b_fname, "");
  538.                 }
  539.                 bp->b_dotp = bp->b_linep;
  540.                 bp->b_doto = 0;
  541.                 ffile = FALSE;
  542.             } else {
  543.                 /* set this to inactive */
  544.                 bp = bfind(bname, TRUE, 0);
  545.                 strcpy(bp->b_fname, argv[carg]);
  546.                 bp->b_active = FALSE;
  547.             }
  548.  
  549.             /* set the view mode appropriatly */
  550.             if (viewflag)
  551.                 bp->b_mode |= MDVIEW;
  552.         }
  553.     }
  554.  
  555.     /* if invoked with nothing, run the startup file here */
  556.     if (startf == FALSE) {
  557.         startup("");
  558.         startf = TRUE;
  559. #if    COLOR
  560.         curwp->w_fcolor = gfcolor;
  561.         curwp->w_bcolor = gbcolor;
  562. #endif
  563.     }
  564.  
  565.         /* Deal with startup gotos and searches */
  566.  
  567.         if (gotoflag && searchflag) {
  568.             update(FALSE);
  569.         mlwrite("[Can not search and goto at the same time!]");
  570.     }
  571.         else if (gotoflag) {
  572.                 if (gotoline(NULL,gline) == FALSE) {
  573.                     update(FALSE);
  574.             mlwrite("[Bogus goto argument]");
  575.         }
  576.         } else if (searchflag) {
  577.                 if (forscan(&pat[0], 2) == FALSE) {
  578.                     update(FALSE);
  579.             mlwrite("Not found.");
  580.         }
  581.         }
  582.  
  583.     /* setup to process commands */
  584.         lastflag = 0;                           /* Fake last flags.     */
  585.     curbp->b_mode |= gmode;            /* and set default modes*/
  586.     curwp->w_flag |= WFMODE;        /* and force an update    */
  587.  
  588. loop:
  589.         update(FALSE);                          /* Fix up the screen    */
  590.         c = getcmd();
  591.         if (mpresf != FALSE) {
  592.                 mlerase();
  593.                 update(FALSE);
  594. #if    CLRMSG
  595.                 if (c == ' ')                   /* ITS EMACS does this  */
  596.                         goto loop;
  597. #endif
  598.         }
  599.         f = FALSE;
  600.         n = 1;
  601.  
  602.     /* do META-# processing if needed */
  603.  
  604.     basec = c & ~META;        /* strip meta char off if there */
  605.     if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
  606.         f = TRUE;        /* there is a # arg */
  607.         n = 0;            /* start with a zero default */
  608.         mflag = 1;        /* current minus flag */
  609.         c = basec;        /* strip the META */
  610.         while ((c >= '0' && c <= '9') || (c == '-')) {
  611.             if (c == '-') {
  612.                 /* already hit a minus or digit? */
  613.                 if ((mflag == -1) || (n != 0))
  614.                     break;
  615.                 mflag = -1;
  616.             } else {
  617.                 n = n * 10 + (c - '0');
  618.             }
  619.             if ((n == 0) && (mflag == -1))    /* lonely - */
  620.                 mlwrite("Arg:");
  621.             else
  622.                 mlwrite("Arg: %d",n * mflag);
  623.  
  624.             c = getcmd();    /* get the next key */
  625.         }
  626.         n = n * mflag;    /* figure in the sign */
  627.     }
  628.  
  629.     /* do ^U repeat argument processing */
  630.  
  631.         if (c == reptc) {                  /* ^U, start argument   */
  632.                 f = TRUE;
  633.                 n = 4;                          /* with argument of 4 */
  634.                 mflag = 0;                      /* that can be discarded. */
  635.                 mlwrite("Arg: 4");
  636.                 while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){
  637.                         if (c == reptc)
  638.                 if ((n > 0) == ((n*4) > 0))
  639.                                     n = n*4;
  640.                             else
  641.                                 n = 1;
  642.                         /*
  643.                          * If dash, and start of argument string, set arg.
  644.                          * to -1.  Otherwise, insert it.
  645.                          */
  646.                         else if (c == '-') {
  647.                                 if (mflag)
  648.                                         break;
  649.                                 n = 0;
  650.                                 mflag = -1;
  651.                         }
  652.                         /*
  653.                          * If first digit entered, replace previous argument
  654.                          * with digit and set sign.  Otherwise, append to arg.
  655.                          */
  656.                         else {
  657.                                 if (!mflag) {
  658.                                         n = 0;
  659.                                         mflag = 1;
  660.                                 }
  661.                                 n = 10*n + c - '0';
  662.                         }
  663.                         mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  664.                 }
  665.                 /*
  666.                  * Make arguments preceded by a minus sign negative and change
  667.                  * the special argument "^U -" to an effective "^U -1".
  668.                  */
  669.                 if (mflag == -1) {
  670.                         if (n == 0)
  671.                                 n++;
  672.                         n = -n;
  673.                 }
  674.         }
  675.  
  676.         if (kbdmip != NULL) {                   /* Save macro strokes.  */
  677.                 if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) {
  678.                         ctrlg(FALSE, 0);
  679.                         goto loop;
  680.                 }
  681.                 if (f != FALSE) {
  682.                         *kbdmip++ = reptc;
  683.                         *kbdmip++ = n;
  684.                 }
  685.                 *kbdmip++ = c;
  686.         }
  687.         execute(c, f, n);                       /* Do it.               */
  688.         goto loop;
  689. }
  690.  
  691. /*
  692.  * Initialize all of the buffers and windows. The buffer name is passed down
  693.  * as an argument, because the main routine may have been told to read in a
  694.  * file by default, and we want the buffer name to be right.
  695.  */
  696. edinit(bname)
  697. char    bname[];
  698. {
  699.         register BUFFER *bp;
  700.         register WINDOW *wp;
  701.     char *malloc();
  702.  
  703.         bp = bfind(bname, TRUE, 0);             /* First buffer         */
  704.         blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer   */
  705.         wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window         */
  706.         if (bp==NULL || wp==NULL || blistp==NULL)
  707.                 exit(1);
  708.         curbp  = bp;                            /* Make this current    */
  709.         wheadp = wp;
  710.         curwp  = wp;
  711.         wp->w_wndp  = NULL;                     /* Initialize window    */
  712.         wp->w_bufp  = bp;
  713.         bp->b_nwnd  = 1;                        /* Displayed.           */
  714.         wp->w_linep = bp->b_linep;
  715.         wp->w_dotp  = bp->b_linep;
  716.         wp->w_doto  = 0;
  717.         wp->w_markp = NULL;
  718.         wp->w_marko = 0;
  719.         wp->w_toprow = 0;
  720. #if    COLOR
  721.     /* initalize colors to global defaults */
  722.     wp->w_fcolor = gfcolor;
  723.     wp->w_bcolor = gbcolor;
  724. #endif
  725.         wp->w_ntrows = term.t_nrow-1;           /* "-1" for mode line.  */
  726.         wp->w_force = 0;
  727.         wp->w_flag  = WFMODE|WFHARD;            /* Full.                */
  728. }
  729.  
  730. /*
  731.  * This is the general command execution routine. It handles the fake binding
  732.  * of all the keys to "self-insert". It also clears out the "thisflag" word,
  733.  * and arranges to move it to the "lastflag", so that the next command can
  734.  * look at it. Return the status of command.
  735.  */
  736. execute(c, f, n)
  737. {
  738.         register KEYTAB *ktp;
  739.         register int    status;
  740.  
  741.         ktp = &keytab[0];                       /* Look in key table.   */
  742.         while (ktp->k_fp != NULL) {
  743.                 if (ktp->k_code == c) {
  744.                         thisflag = 0;
  745.                         status   = (*ktp->k_fp)(f, n);
  746.                         lastflag = thisflag;
  747.                         return (status);
  748.                 }
  749.                 ++ktp;
  750.         }
  751.  
  752.         /*
  753.          * If a space was typed, fill column is defined, the argument is non-
  754.          * negative, wrap mode is enabled, and we are now past fill column,
  755.      * and we are not read-only, perform word wrap.
  756.          */
  757.         if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  758.         n >= 0 && getccol(FALSE) > fillcol &&
  759.         (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  760.                 wrapword();
  761.  
  762.         if ((c>=0x20 && c<=0x7E)                /* Self inserting.      */
  763.         ||  (c>=0xA0 && c<=0xFE)) {
  764.                 if (n <= 0) {                   /* Fenceposts.          */
  765.                         lastflag = 0;
  766.                         return (n<0 ? FALSE : TRUE);
  767.                 }
  768.                 thisflag = 0;                   /* For the future.      */
  769.  
  770.         /* if we are in overwrite mode, not at eol,
  771.            and next char is not a tab or we are at a tab stop,
  772.            delete a char forword            */
  773.         if (curwp->w_bufp->b_mode & MDOVER &&
  774.             curwp->w_doto < curwp->w_dotp->l_used &&
  775.             (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
  776.              (curwp->w_doto) % 8 == 7))
  777.                 ldelete(1L, FALSE);
  778.  
  779.         /* do the appropriate insertion */
  780.         if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
  781.                 status = insbrace(n, c);
  782.             else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
  783.                 status = inspound();
  784.             else
  785.                     status = linsert(n, c);
  786.  
  787. #if    CFENCE
  788.         /* check for CMODE fence matching */
  789.         if ((c == '}' || c == ')') && (curbp->b_mode & MDCMOD) != 0)
  790.             fmatch(c);
  791. #endif
  792.  
  793.                 lastflag = thisflag;
  794.                 return (status);
  795.         }
  796.     (*term.t_beep)();
  797.     mlwrite("[Key not bound]");        /* complain        */
  798.         lastflag = 0;                           /* Fake last flags.     */
  799.         return (FALSE);
  800. }
  801.  
  802. /*
  803.  * Fancy quit command, as implemented by Norm. If the any buffer has
  804.  * changed do a write on that buffer and exit emacs, otherwise simply exit.
  805.  */
  806. quickexit(f, n)
  807. {
  808.     register BUFFER *bp;    /* scanning pointer to buffers */
  809.  
  810.     bp = bheadp;
  811.     while (bp != NULL) {
  812.             if ((bp->b_flag&BFCHG) != 0    /* Changed.             */
  813.             && (bp->b_flag&BFINVS) == 0) {    /* Real.                */
  814.             curbp = bp;        /* make that buffer cur    */
  815.             mlwrite("[Saving %s]",bp->b_fname);
  816.                     filesave(f, n);
  817.         }
  818.     bp = bp->b_bufp;            /* on to the next buffer */
  819.     }
  820.         quit(f, n);                             /* conditionally quit   */
  821. }
  822.  
  823. /*
  824.  * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  825.  * has been changed and not written out. Normally bound to "C-X C-C".
  826.  */
  827. quit(f, n)
  828. {
  829.         register int    s;
  830.  
  831.         if (f != FALSE                          /* Argument forces it.  */
  832.         || anycb() == FALSE                     /* All buffers clean.   */
  833.                         /* User says it's OK.   */
  834.         || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
  835. #if    FILOCK
  836.         if (lockrel() != TRUE) {
  837.             (*term.t_putchar)('\n');
  838.             (*term.t_putchar)('\r');
  839.             (*term.t_close)();
  840.             (*term.t_kclose)();
  841.             exit(1);
  842.         }
  843. #endif
  844.                 vttidy();
  845. #if    APROF
  846.         /* if doing AZTEC C profiling, close up and write it out */
  847.         monitor(0,0,0,0,0);
  848. #endif
  849.                 exit(GOOD);
  850.         }
  851.     mlwrite("");
  852.         return (s);
  853. }
  854.  
  855. /*
  856.  * Begin a keyboard macro.
  857.  * Error if not at the top level in keyboard processing. Set up variables and
  858.  * return.
  859.  */
  860. ctlxlp(f, n)
  861. {
  862.         if (kbdmip!=NULL || kbdmop!=NULL) {
  863.                 mlwrite("Not now");
  864.                 return (FALSE);
  865.         }
  866.         mlwrite("[Start macro]");
  867.         kbdmip = &kbdm[0];
  868.         return (TRUE);
  869. }
  870.  
  871. /*
  872.  * End keyboard macro. Check for the same limit conditions as the above
  873.  * routine. Set up the variables and return to the caller.
  874.  */
  875. ctlxrp(f, n)
  876. {
  877.         if (kbdmip == NULL) {
  878.                 mlwrite("Not now");
  879.                 return (FALSE);
  880.         }
  881.         mlwrite("[End macro]");
  882.         kbdmip = NULL;
  883.         return (TRUE);
  884. }
  885.  
  886. /*
  887.  * Execute a macro.
  888.  * The command argument is the number of times to loop. Quit as soon as a
  889.  * command gets an error. Return TRUE if all ok, else FALSE.
  890.  */
  891. ctlxe(f, n)
  892. {
  893.         register int    c;
  894.         register int    af;
  895.         register int    an;
  896.         register int    s;
  897.  
  898.         if (kbdmip!=NULL || kbdmop!=NULL) {
  899.                 mlwrite("Not now");
  900.                 return (FALSE);
  901.         }
  902.         if (n <= 0)
  903.                 return (TRUE);
  904.         do {
  905.                 kbdmop = &kbdm[0];
  906.                 do {
  907.                         af = FALSE;
  908.                         an = 1;
  909.                         if ((c = *kbdmop++) == reptc) {
  910.                                 af = TRUE;
  911.                                 an = *kbdmop++;
  912.                                 c  = *kbdmop++;
  913.                         }
  914.                         s = TRUE;
  915.                 } while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
  916.                 kbdmop = NULL;
  917.         } while (s==TRUE && --n);
  918.         return (s);
  919. }
  920.  
  921. /*
  922.  * Abort.
  923.  * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  924.  * Sometimes called as a routine, to do general aborting of stuff.
  925.  */
  926. ctrlg(f, n)
  927. {
  928.         (*term.t_beep)();
  929.         if (kbdmip != NULL) {
  930.                 kbdm[0] = (CTLX|')');
  931.                 kbdmip  = NULL;
  932.         }
  933.     mlwrite("[Aborted]");
  934.         return (ABORT);
  935. }
  936.  
  937. /* tell the user that this command is illegal while we are in
  938.    VIEW (read-only) mode                */
  939.  
  940. rdonly()
  941.  
  942. {
  943.     (*term.t_beep)();
  944.     mlwrite("[Key illegal in VIEW mode]");
  945.     return(FALSE);
  946. }
  947.  
  948. meta()    /* dummy function for binding to meta prefix */
  949. {
  950. }
  951.  
  952. cex()    /* dummy function for binding to control-x prefix */
  953. {
  954. }
  955.  
  956. unarg()    /* dummy function for binding to universal-argument */
  957. {
  958. }
  959.